package com.example.ndktest;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import android.util.Log;

import com.example.ndktest.Encoder.rawData;

public class Decoder implements Runnable{

	private Consumer consumer;
	private Object mutex = new Object();
	private boolean isDataAvailable = false;
	private Speex speex = new Speex();
	private long ts;
	private short[] processedData = new short[1024];
	private byte[] rawdata = new byte[1024];
	private volatile int leftSize = 0;
	private boolean isRunning;
	private PcmWriter pcmWriter;
	private List<RawData> list;
	private static final String LOG_BUSHCAT = "Log_bushcat";
	
	public Decoder(Consumer consumer)
	{
		super();
		this.consumer = consumer;
		isRunning = true;
		speex.init();
		
		list = Collections.synchronizedList(new LinkedList<RawData>());
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		android.os.Process
		.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
		
		int getSize = 0;
		
		//test
		pcmWriter = new PcmWriter("/android_Rec_decoded_1.pcm");
		pcmWriter.init();
		pcmWriter.setRecording(true);
		Thread pcmWriterThread = new Thread(pcmWriter);
		pcmWriterThread.start();
		//
		
		while(isRunning)
		{
			if (isIdleNew()) {
				try {
					Thread.sleep(20);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				continue;
			}
			//synchronized (mutex) {
				while(list.size() > 0)
				{
					RawData tempData = list.remove(0);
					getSize = speex.decode(tempData.data, processedData, tempData.size);
					pcmWriter.putData(processedData, getSize);
					setIdle();
					Log.i(LOG_BUSHCAT, "Decoded : " + getSize);
				
					if (getSize > 0) {
						consumer.putDecodedData(ts, processedData, getSize);
					}
				}
			//}
		}
	}
	
	public void stop(boolean running)
	{
		isRunning = false;
		pcmWriter.setRecording(false);
	}
	
	public void putData(long ts, byte[] data, int size) {
		synchronized (mutex) {
			this.ts = ts;
			System.arraycopy(data, 0, rawdata, 0, size);
			this.leftSize = size;
		}
	}
	
	public void putDataNew(byte[] data, int size)
	{
		//synchronized(mutex){
			RawData tempData = new RawData();
			
			tempData.size = size;
			System.arraycopy(data, 0, tempData.data, 0, size);

			list.add(tempData);
		//}
	}

	public boolean isIdle() {
		synchronized (mutex) {
			return leftSize == 0 ? true : false;
		}
	}
	
	public boolean isIdleNew(){
		synchronized(mutex){
			return list.size() == 0 ? true : false;
		}
	}

	public void setIdle() {
		leftSize = 0;
	}
	
	public void dataAvailable()
	{
		synchronized (mutex)
		{
			isDataAvailable = true;
		}
	}
	
	public boolean isDataAvailable()
	{
		synchronized (mutex)
		{
			return isDataAvailable;
		}
	}
	
	class RawData {
		int size;
		byte[] data = new byte[1024];
	}

}
